import AudioManager, { ESoundType } from "../Util/AudioManager";

/**
 * 自定义按钮类
 * 
 * 过渡类型: 无过渡、缩放过渡、颜色过渡、精灵过渡
 * 
 * 添加按钮防止误点、点击音效等功能
 * @desc 点击音效: 点击时播放点击音效
* @desc 按钮防止误点: 每次点击完后添加一段时间不可点击(等请求返回)
*/
const { ccclass, property, executeInEditMode, help } = cc._decorator;

@ccclass
@help("i18n:COMPONENT.help_url.button")
export default class CustomButton extends cc.Component {

    @property({
        type: cc.Node,
        tooltip: CC_DEV && "i18n:COMPONENT.button.target"
    })
    private target: cc.Node = null;

    @property({
        type: cc.AudioClip,
        displayName: "Audio",
        tooltip: CC_DEV && "按钮触发时播放音频",
    })
    private clickAudio: cc.AudioClip = null;

    @property({
        tooltip: CC_DEV && 'i18n:COMPONENT.button.interactable'
    })
    public interactable: boolean = true;

    @property({ tooltip: "按钮防误点", range: [0, 10], step: 0.1 })
    private delayTime: number = 0;

    @property({ tooltip: "按钮动画缩放比例", range: [0, 10], step: 0.05 })
    private animRatio: number = 1;

    @property({
        tooltip: "动画缩放时间(缩||放)", range: [0, 10], step: 0.01,
        visible() {
            return this.animationRatio !== 1;
        }
    })
    private animTime: number = 0.8;

    @property({
        type: cc.Button.Transition,
        tooltip: CC_DEV && 'i18n:COMPONENT.button.transition',
        animatable: false,
        formerlySerializedAs: 'transition'
    })
    private transitionType: cc.Button.Transition = cc.Button.Transition.NONE;

    @property({
        type: cc.SpriteFrame,
        displayName: 'Normal',
        tooltip: CC_DEV && 'i18n:COMPONENT.button.normal_sprite',
        visible() {
            return this.transitionType === cc.Button.Transition.SPRITE;
        }
    })
    private normalSprite: cc.SpriteFrame = null;

    @property({
        type: cc.SpriteFrame,
        displayName: 'Pressed',
        tooltip: CC_DEV && 'i18n:COMPONENT.button.pressed_sprite',
        visible() {
            return this.transitionType === cc.Button.Transition.SPRITE;
        }
    })
    private pressedSprite: cc.SpriteFrame = null;

    @property({
        type: cc.SpriteFrame,
        displayName: 'Hover',
        tooltip: CC_DEV && 'i18n:COMPONENT.button.hover_sprite',
        visible() {
            return this.transitionType === cc.Button.Transition.SPRITE;
        }
    })
    private hoverSprite: cc.SpriteFrame = null;

    @property({
        type: cc.SpriteFrame,
        displayName: 'Disabled',
        tooltip: CC_DEV && 'i18n:COMPONENT.button.disabled_sprite',
        visible() {
            return this.transitionType === cc.Button.Transition.SPRITE;
        }
    })
    private disabledSprite: cc.SpriteFrame = null;

    @property({
        displayName: 'Normal',
        tooltip: CC_DEV && 'i18n:COMPONENT.button.normal_color',
        visible() {
            return this.transitionType === cc.Button.Transition.COLOR;
        }
    })
    private normalColor: cc.Color = cc.Color.WHITE;

    @property({
        displayName: 'Pressed',
        tooltip: CC_DEV && 'i18n:COMPONENT.button.pressed_color',
        visible() {
            return this.transitionType === cc.Button.Transition.COLOR;
        },
    })
    private pressedColor: cc.Color = cc.color(211, 211, 211);

    @property({
        displayName: 'Hover',
        tooltip: CC_DEV && 'i18n:COMPONENT.button.pressed_color',
        visible() {
            return this.transitionType === cc.Button.Transition.COLOR;
        },
    })
    private hoverColor: cc.Color = cc.Color.WHITE;

    @property({
        displayName: 'Disabled',
        tooltip: CC_DEV && 'i18n:COMPONENT.button.pressed_color',
        visible() {
            return this.transitionType === cc.Button.Transition.COLOR;
        },
    })
    private disabledColor: cc.Color = cc.color(124, 124, 124);

    @property({
        tooltip: CC_DEV && 'i18n:COMPONENT.button.duration', range: [0, 10], step: 0.1,
        visible() {
            return this.transitionType === cc.Button.Transition.SCALE;
        }
    })
    private duration: number = 0.1;

    @property({
        tooltip: CC_DEV && 'i18n:COMPONENT.button.zoom_scale',
        range: [0, 10], step: 0.1,
        visible() {
            return this.transitionType === cc.Button.Transition.SCALE;
        }
    })
    private zoomScale: number = 1.2;

    @property({
        type: cc.Component.EventHandler,
        tooltip: CC_DEV && 'i18n:COMPONENT.button.click_events'
    })
    public clickEvents: cc.Component.EventHandler[] = [];

    private button: cc.Button = null;

    private ratios: cc.Vec2 = cc.v2(1, 1);
    private scales: cc.Vec2 = cc.v2(1, 1);

    private isaaa: boolean = false;
    protected onLoad() {
        // // 注册按钮自定义事件
        // const clickEventHandler = new cc.Component.EventHandler();
        // clickEventHandler.target = this.node;
        // clickEventHandler.component = "CustomButton";
        // clickEventHandler.handler = "callback";
        // clickEventHandler.customEventData = "";
        // const button = this.node.addComponent(cc.Button);
        // button.clickEvents.push(clickEventHandler);

        this.ratios.x = this.scales.x = this.node.scaleX;
        this.ratios.y = this.scales.y = this.node.scaleY;

        // 注册按钮拖入事件
        this.button = this.node.addComponent(cc.Button);
        this.button.interactable = this.interactable;
        this.clickEvents.forEach((o) => {
            this.button.clickEvents.push(o);
        });

        if (this.target) {
            if (this.transitionType === cc.Button.Transition.COLOR) {
                this.target.color = this.normalColor;
            }
            this.target.getComponent(cc.Sprite).spriteFrame = this.normalSprite;
        }

        this.checkWarn();
        this.playAnimation();
    }

    public setButtonCD(node: cc.Node, cd = 1) {
        if (!node) {
            return;
        }
        
        if (node['inCD']) {
            return false;
        } else {
            node['inCD'] = true;
            setTimeout(() => {
                node['inCD'] = false;
            }, cd * 1000)
        }
        
        return true;
    }

    /**
     * 检测是否含有未拖入节点&&抛出警告
     */
    private checkWarn() {
        if (!this.target) {
            // console.warn(`请拖入CustomButton.background节点~`);
            this.target = this.node;
        }

        if (!this.clickAudio) {
            // console.warn(`请拖入CustomButton点击音效~`);
        }
    }

    /**
     * 按钮动画&&呼吸效果
     * @param animRatio 缩放系数
     * @param animTime 缩放时间(缩||放)
     */
    private playAnimation() {
        if (this.animRatio !== 1) {
            this.node.stopAllActions();
            cc.tween(this.node).repeatForever(
                cc.sequence(
                    cc.scaleTo(0, this.ratios.x, this.ratios.y),
                    cc.scaleTo(this.animTime, this.ratios.x * this.animRatio, this.ratios.x * this.animRatio),
                    cc.scaleTo(this.animTime, this.ratios.x, this.ratios.y),
                )
            ).start();

            // 按钮过渡状态设置成无过渡状态
            this.transitionType = cc.Button.Transition.NONE;
        } else {
            this.node.stopAllActions();
            this.node.scaleX = this.scales.x;
            this.node.scaleY = this.scales.y;

            if (this.isaaa) {
                console.log('playAnimation2222', this.node.scaleX, this.node.scaleY);
            }
        }
    }

    protected onEnable() {
        this.node.on(cc.Node.EventType.TOUCH_START, this.onTouchDown, this);
        this.node.on(cc.Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
        this.node.on(cc.Node.EventType.TOUCH_END, this.onTouchUp, this);
        this.node.on(cc.Node.EventType.TOUCH_CANCEL, this.onTouchCancel, this);

        // 处理按钮tween过程中被隐藏问题
        this.node.stopAllActions();
        this.node.scaleX = this.ratios.x;
        this.node.scaleY = this.ratios.y;
    }

    protected onDisable() {
        this.node.off(cc.Node.EventType.TOUCH_START, this.onTouchDown, this);
        this.node.off(cc.Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
        this.node.off(cc.Node.EventType.TOUCH_END, this.onTouchUp, this);
        this.node.off(cc.Node.EventType.TOUCH_CANCEL, this.onTouchCancel, this);
    }

    /**
     * 按钮按下监听
     */
    private onTouchDown(event) {
        if (!this.setButtonCD(event.currentTarget, this.delayTime)) {
            console.log("CustomButton.onTouchDown()===>cd~");
            return;
        }

        this.button.interactable = this.interactable;
        if (!this.interactable || !this.button.interactable) {
            return;
        }
        
        // 播放点击音效或者默认点击音效
        if (this.clickAudio) {
            cc.audioEngine.playEffect(this.clickAudio, false);
        } else {
            AudioManager.instance.playSound(ESoundType.Click, 2);
        }

        switch (this.transitionType) {
            case cc.Button.Transition.NONE:
                break;
            case cc.Button.Transition.SCALE:
                this.ratios = this.scales;
                this.node.stopAllActions();
                cc.tween(this.node).to(this.duration, { scaleX: this.zoomScale * this.node.scaleX, scaleY: this.zoomScale * this.node.scaleY }).start();
                break;
            case cc.Button.Transition.SPRITE:
                if (this.target) {
                    this.target.getComponent(cc.Sprite).spriteFrame = this.pressedSprite;
                } else {
                    // console.log(GameUtil.instance.getNodePath(this.node));
                }
                break;
            case cc.Button.Transition.COLOR:
                if (this.target) {
                    this.target.color = this.pressedColor;
                } else {
                    // console.log(GameUtil.instance.getNodePath(this.node));
                }
                break;
        }
    }

    /**
     * 按钮移动监听
     */
    private onTouchMove(event) {
        this.button.interactable = this.interactable;
        if (!this.interactable || !this.button.interactable) {
            return;
        }
    }

    /**
     * 按钮抬起监听
     * 抬起是会走callback回调
     */
    private onTouchUp(event) {
        this.button.interactable = this.interactable;
        if (!this.interactable || !this.button.interactable) {
            return;
        }

        switch (this.transitionType) {
            case cc.Button.Transition.NONE:
                break;
            case cc.Button.Transition.SCALE:
                this.node.stopAllActions();
                cc.tween(this.node).to(this.duration, { scaleX: this.ratios.x, scaleY: this.ratios.y }).start();
                break;
            case cc.Button.Transition.SPRITE:
                if (this.target) {
                    this.target.getComponent(cc.Sprite).spriteFrame = this.normalSprite;
                }
                break;
            case cc.Button.Transition.COLOR:
                if (this.target) {
                    this.target.color = this.normalColor;
                }
                break;
        }
    }

    /**
     * 按钮取消监听
     */
    private onTouchCancel(event) {
        this.button.interactable = this.interactable;
        if (!this.interactable || !this.button.interactable) {
            return;
        }

        switch (this.transitionType) {
            case cc.Button.Transition.NONE:
                break;
            case cc.Button.Transition.SCALE:
                this.node.stopAllActions();
                cc.tween(this.node).to(this.duration, { scaleX: this.ratios.x, scaleY: this.ratios.y }).start();
                break;
            case cc.Button.Transition.SPRITE:
                if (this.target) {
                    this.target.getComponent(cc.Sprite).spriteFrame = this.normalSprite;
                } else {
                    // console.log(GameUtil.instance.getNodePath(this.node));
                }
                break;
            case cc.Button.Transition.COLOR:
                if (this.target) {
                    this.target.color = this.normalColor;
                } else {
                    // console.log(GameUtil.instance.getNodePath(this.node));
                }
                break;
        }
    }
}